package memory;

import java.io.File;
import java.io.FileNotFoundException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.Scanner;
import java.util.regex.Pattern;
import javax.swing.JOptionPane;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

/**
 *
 * @author Scott Robinson
 */
public class Log {
    

    //private static final String FILE_NAME = "GUI\\highScores\\highScores.txt";
    //private static final String FILE_NAME = "C:\\Users\\Scott\\Desktop\\Java Programs\\Algorithms & Data Struc III\\Memory\\Memory\\GUI\\highScores\\highScores.txt";
    private static final String WINNER_MESSAGE = "Congratulations, you set a new speed record!\n" +
            "Please enter your name for the high score board: ";
    private static final String FILE_NAME = "GUI\\HighScore\\highScores.txt";
    private File file;
    private  List<Winner> easy, simple, medium, hard;
    private GameDifficulty gd ;
    private final GameDifficulty currentDifficulty;
    private final Calendar userCal;

    public Log () {
        currentDifficulty = null;
        userCal = null;
        easy = new ArrayList<Winner>();
        simple = new ArrayList<Winner>();
        medium = new ArrayList<Winner>();
        hard = new ArrayList<Winner>();
        setFile(FILE_NAME);
        scanLines();
    }

    public Log(Calendar cal, GameDifficulty currentDifficulty) {       

        try {
            UIManager.setLookAndFeel("com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel");
        } catch (ClassNotFoundException ex) {
            ex.printStackTrace();
        } catch (InstantiationException ex) {
            ex.printStackTrace();
        } catch (IllegalAccessException ex) {
            ex.printStackTrace();
        } catch (UnsupportedLookAndFeelException ex) {
            ex.printStackTrace();
        }

        this.currentDifficulty = currentDifficulty;
        userCal = cal;
        gd = GameDifficulty.EASY;
        setFile(FILE_NAME);

        easy = new ArrayList<Winner>();
        simple = new ArrayList<Winner>();
        medium = new ArrayList<Winner>();
        hard = new ArrayList<Winner>();

        scanLines();

        Winner winner = new Winner (cal, "temp");
            if (currentDifficulty.equals(GameDifficulty.SIMPLE)) {
                simple.add(winner);
                Collections.sort(simple);
                simple.remove(3);
                if (simple.contains(winner)) {
                    promptForName(winner);
                }
            }
            else if (currentDifficulty.equals(GameDifficulty.EASY)) {
                easy.add(winner);
                Collections.sort(easy);
                easy.remove(3);
                if (easy.contains(winner)) {
                    promptForName(winner);
                }
            }
            else if (currentDifficulty.equals(GameDifficulty.MEDIUM)) {
                medium.add(winner);
                Collections.sort(medium);
                medium.remove(3);
                if (medium.contains(winner)) {
                    promptForName(winner);
                }
            }
            else if (currentDifficulty.equals(GameDifficulty.HARD)) {
                hard.add(winner);
                Collections.sort(hard);
                hard.remove(3);
                if (hard.contains(winner)) {
                    promptForName(winner);
                }
            }

        writeLog();
    }

    public void setFile(String file) {
        try {
            this.file = new File(file);
        }
        catch (Error e) {
            System.out.println("File Not Found!");
            System.exit(1);
        }
    }

    public File getFile() {
        return file;
    }

    public void scanLines() {
        Scanner scanner = null;
        try {
            File tempFile = new File(getFile().getAbsolutePath());
//            System.out.println(tempFile.getAbsolutePath());
//            System.out.println(tempFile.toString());
            scanner = new Scanner(tempFile);
        } catch (FileNotFoundException ex) {
            System.err.print("Error loading the file!  The file trying to be loaded is located at: ");
            System.err.println(getFile().getAbsolutePath());
            System.exit(1);
        }

        while (scanner.hasNextLine()) {
            String temp = scanner.nextLine().trim();
            //System.out.println("The line being parsed is: " + temp);
            if (temp.equalsIgnoreCase(GameDifficulty.EASY.name().trim())) {
                gd = GameDifficulty.EASY;
                //System.out.println("That line matches " + GameDifficulty.EASY.name());
            }
            else if (temp.equalsIgnoreCase(GameDifficulty.MEDIUM.name().trim())) {
                gd = GameDifficulty.MEDIUM;
                //System.out.println("That line matches " + GameDifficulty.MEDIUM.name());
            }
            else if (temp.equalsIgnoreCase(GameDifficulty.HARD.name().trim())) {
                gd = GameDifficulty.HARD;
                //System.out.println("That line matches " + GameDifficulty.HARD.name());
            }
            else if (temp.equalsIgnoreCase(GameDifficulty.SIMPLE.name().trim())) {
                gd = GameDifficulty.SIMPLE;
                //System.out.println("That line matches " + GameDifficulty.SIMPLE.name());
            }
            else {
                //System.out.println("That line is being passed to scanWords");
                scanWords(temp);
            }
        }
        scanner.close();
    }

    public String [] getSimpleWinners() {
        String s [] = new String[3];
        Iterator <Winner> it = simple.iterator();
        for ( int ii = 0; ii < 3; ii++) {
            s[ii] = it.next().toString();
        }
        return s;
    }

    public String [] getEasyWinners() {
        String s [] = new String[3];
        Iterator <Winner> it = easy.iterator();
        for ( int ii = 0; ii < 3; ii++) {
            s[ii] = it.next().toString();
        }
        return s;
    }

    public String [] getMediumWinners() {
        String s [] = new String[3];
        Iterator <Winner> it = medium.iterator();
        for ( int ii = 0; ii < 3; ii++) {
            s[ii] = it.next().toString();
        }
        return s;
    }

    public String [] getHardWinners() {
        String s [] = new String[3];
        Iterator <Winner> it = hard.iterator();
        for ( int ii = 0; ii < 3; ii++) {
            s[ii] = it.next().toString();
        }
        return s;
    }

    public void writeLog () {
        StringBuilder sb = new StringBuilder();
        sb.append(GameDifficulty.SIMPLE.name().trim());
        sb.append("\n");
        for (Winner w : simple) {
            sb.append(w);
            sb.append("\n");
        }
        sb.append(GameDifficulty.EASY.name().trim());
        sb.append("\n");
        for (Winner w : easy) {
            sb.append(w);
            sb.append("\n");
        }
        sb.append(GameDifficulty.MEDIUM.name().trim());
        sb.append("\n");
        for (Winner w : medium) {
            sb.append(w);
            sb.append("\n");
        }
        sb.append(GameDifficulty.HARD.name().trim());
        sb.append("\n");
        for (Winner w : hard) {
            sb.append(w);
            sb.append("\n");
        }
        try {

            Formatter output = new Formatter(file.getAbsoluteFile());
            output.format("%s", sb.toString());
            output.close();

        } catch (FileNotFoundException ex) {
            System.err.println("Error writing file!");
            System.err.println(ex);
        }
    }

    public void scanWords (String str) {
            Scanner sc = new Scanner(str);
            String time [] = new String[2];
            time = sc.next().split(":");
            int m = Integer.parseInt(time[0]);
            int s = Integer.parseInt(time[1]);

            Calendar c = Calendar.getInstance();
            c.setTimeInMillis(0);
            c.add(Calendar.MINUTE, m);
            c.add(Calendar.SECOND, s);
            
            StringBuilder sb = new StringBuilder();
            while (sc.hasNext()) {
                sb.append(sc.next());
                sb.append(" ");
            }
            Winner winner = new Winner (c,sb.toString());
            if (gd.equals(GameDifficulty.SIMPLE)) {
                simple.add(winner);
            }
            else if (gd.equals(GameDifficulty.EASY)) {
                easy.add(winner);
            }
            else if (gd.equals(GameDifficulty.MEDIUM)) {
                medium.add(winner);
            }
            else if (gd.equals(GameDifficulty.HARD)) {
                hard.add(winner);
            }
            //System.out.println("The value parsed and added is: " + winner.toString());
    }

    private void promptForName(Winner winner) {
        String temp = JOptionPane.showInputDialog(WINNER_MESSAGE);
        if (isValidInput(temp)) {
            winner.setName(temp);
        }
        else {
            while (!isValidInput(temp)) {
                JOptionPane.showMessageDialog(null, "Invalid Input!  First and/or last name only, only the first letter\n" +
                        "may be capitalized, and only characters may be used.  Please try again.");
                temp = JOptionPane.showInputDialog(WINNER_MESSAGE);
            }
           winner.setName(temp);
        }
    }

    private boolean isValidInput (String s) {
        String regex = "([A-Z][a-z]*|[a-z]+)" + // capitol or non caps letters only - basically their first name
                "|(([A-Z][a-z]*\\s|[a-z]+\\s)([A-Z][a-z]*|[a-z]+))"; // or they could enter first and last name
        return Pattern.matches(regex, s);
    }

    private class Winner implements Comparable <Winner> {
        private Calendar c;
        private String name;
        public Winner (Calendar c, String name) {
            this.c = c;
            this.name = name;
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }


        public Calendar getCalendar() {
            return c;
        }

        public int compareTo(Winner that) {
            if (this.getCalendar().before(that.getCalendar())) {
                return -1;
            }
            else if (this.getCalendar().equals(that.getCalendar())) {
                return 0;
            }
            else
                return 1;
        }

        @Override
        public boolean equals(Object obj) {
            if (obj == null) {
                return false;
            }
            if (getClass() != obj.getClass()) {
                return false;
            }
            final Winner other = (Winner) obj;
            if (this.c != other.c && (this.c == null || !this.c.equals(other.c))) {
                return false;
            }
            return true;
        }

        @Override
        public int hashCode() {
            int hash = 3;
            hash = 97 * hash + (this.c != null ? this.c.hashCode() : 0);
            return hash;
        }

        @Override
        public String toString () {
            SimpleDateFormat formatter = new SimpleDateFormat("mm:ss");
            return formatter.format(getCalendar().getTime()) + " " + getName();
        }


    }
}
